package com.example.service;

import com.example.domain.Clazz;
import com.example.domain.Course;
import com.example.domain.Schedule;
import com.example.domain.Teacher;
import com.example.repository.ScheduleRepository;
import com.example.util.EasyuiResult;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


@Service
@Slf4j
public class ScheduleService {
    
    @Autowired
    private ScheduleRepository repository;
    
    @Autowired
    private CourseService courseService;
    @Autowired
    private TeacherService teacherService;
    @Autowired
    private ClazzService clazzService;
    
    @Autowired
    private ScoreService scoreService;
    
    @Transactional
    public List<Course> getAllCourseByTeacherId(int id) {
        Iterable<Schedule> result = repository.findAllByTeacherId(id);
        List<Schedule> list = Lists.newArrayList(result);
        Set<Integer> ids = list.stream().map(l -> l.getCourse().getId()).collect(Collectors.toSet());
        List<Course> courses = courseService.findAllById(ids);
        return courses;
    }
    
    @Transactional
    public List<Schedule> list() {
        return Lists.newArrayList(repository.findAll());
    }
    
    @Transactional
    public List<Schedule> list(final int clazzid, final int courseid) {
        final Page<Schedule> all = repository.findAllByClazzIdAndCourseId(clazzid, courseid, null);
        return all.getContent();
    }
    
    @Transactional
    public EasyuiResult<Schedule> list(final int page, final int rows, final String sortColumn, final String order, final int clazzid, final int courseid, final int teacherid) {
        
        log.info("课程列表,参数为 page={},row={},sortColumn={},order={},clazzid={},courseid={},teacherid={}",
                page, rows, sortColumn, order, clazzid, courseid, teacherid);
        // if (clazzid > 0) {
        //     Specification<Schedule> specClazzId = new Specification<Schedule>() {
        //         @Override
        //         public Predicate toPredicate(final Root<Schedule> root, final CriteriaQuery<?> query, final CriteriaBuilder criteriaBuilder) {
        //             final Path<Object> clazzId = root.get("clazz").get("id");
        //             final Predicate pre = criteriaBuilder.equal(clazzId, clazzid);
        //             return pre;
        //         }
        //     };
        // // }
        
        
        Sort sort = new Sort(Sort.Direction.fromString(order), sortColumn);
        final PageRequest pageRequest = PageRequest.of(page, rows, sort);
        Page<Schedule> all;
        // all = repository.findAll(specClazzId, pageRequest);
        
        if (clazzid > 0 && courseid > 0 && teacherid > 0) {
            all = repository.findAllByClazzIdAndCourseIdAndTeacherId(clazzid, courseid, teacherid, pageRequest);
        } else if (clazzid > 0 && courseid > 0 && teacherid == 0) {
            all = repository.findAllByClazzIdAndCourseId(clazzid, courseid, pageRequest);
        } else if (clazzid > 0 && courseid == 0 && teacherid > 0) {
            all = repository.findAllByClazzIdAndTeacherId(clazzid, teacherid, pageRequest);
        } else if (clazzid > 0 && courseid == 0 && teacherid == 0) {
            all = repository.findAllByClazzId(clazzid, pageRequest);
        } else if (clazzid == 0 && courseid > 0 && teacherid > 0) {
            all = repository.findAllByCourseIdAndTeacherId(courseid, teacherid, pageRequest);
        } else if (clazzid == 0 && courseid > 0 && teacherid == 0) {
            all = repository.findAllByCourseId(courseid, pageRequest);
        } else if (clazzid == 0 && courseid == 0 && teacherid > 0) {
            all = repository.findAllByTeacherId(teacherid, pageRequest);
        } else {
            all = repository.findAll(pageRequest);
        }
        // all.stream().forEach(System.out::println);
        
        final List<Schedule> students = all.getContent();
        
        EasyuiResult<Schedule> result = new EasyuiResult<>();
        result.setRows(students);
        result.setTotal(all.getTotalElements());
        return result;
    }
    
    /**
     * 根据id删除schedule信息,要先删除该schedule对应的score信息.
     * @param id 课程id
     */
    @Transactional
    public void delete(final int id) {
        log.debug("删除课程,id={}", id);
        scoreService.deleteByScheduleId(Lists.newArrayList(id));
        repository.deleteById(id);
    }
    
    @Transactional
    public String add(final int clazzid, final int courseid, final int teacherid) {
        log.debug("添加或更新课程信息,参数为: clazzid={},courseid={},teacherid={}", clazzid, courseid, teacherid);
        Page<Schedule> schedulePage = repository.findAllByClazzIdAndCourseIdAndTeacherId(clazzid, courseid,
                teacherid, null);
        List<Schedule> content = schedulePage.getContent();
        
        // 已有相对应的课程,教师没变,直接返回
        if (content.size() > 0) {
            log.debug("课程表中已经有 clazzid={},courseid={},teacherid={}  的数据了,不需要操作", clazzid, courseid, teacherid);
            return "nothing";
        }
        
        // 已有相对的课程,但是教师变化了.
        schedulePage = repository.findAllByClazzIdAndCourseId(clazzid, courseid, null);
        content = schedulePage.getContent();
        if (content.size() > 0) {
            final Schedule temp = content.get(0);
            final Teacher tempTeacher = teacherService.getById(teacherid);
            temp.setTeacher(tempTeacher);
            repository.save(temp);
            log.debug("课程表中已经有 clazzid={},courseid={}  的数据,但是teacher不同,更新teacher信息,由 {} 变为 {}",
                    clazzid, courseid, tempTeacher.getId(), teacherid);
            return "update";
        }
        
        final Clazz clazz = clazzService.getById(clazzid);
        final Course course = courseService.getById(courseid);
        final Teacher teacher = teacherService.getById(teacherid);
        if (clazz.getId() > 0 && course.getId() > 0 && teacher.getId() > 0) {
            Schedule schedule = new Schedule();
            schedule.setClazz(clazz);
            schedule.setCourse(course);
            schedule.setTeacher(teacher);
            schedule.setName(clazz.getName() + course.getName());
            final Schedule save = repository.save(schedule);
            log.debug("添加课程信息,参数为: clazzid={},courseid={},teacherid={}", clazzid, courseid, teacherid);
            if (save.getId() > 0) {
                return "add";
            }
        }
        return "error";
    }
    
    public Iterable<Schedule> findAllByClazzId(final Iterable<Integer> clazzids) {
        return repository.findAllByClazz_IdIn(clazzids);
    }
    
    /**
     * 根据班级(clazzids)删除课程表信息.要先删除成绩表(score)对应的信息
     * @param clazzids
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void deleteByClazzId(final Iterable<Integer> clazzids) {
        scoreService.deleteByClazzId(clazzids);
        repository.deleteAllByClazz_IdIn(clazzids);
    }
}
